package com.cet.recon.writer;

import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.batch.item.Chunk;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemStream;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.ItemWriter;

import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @author 30952
 */
public class ExcelReconItemWriter implements ItemStream, ItemWriter<Map<String, Object>> {

    private final Path outPath;
    private Workbook wb;
    private final Map<String, Sheet> sheets = new HashMap<>();

    public ExcelReconItemWriter(Path outPath) {
        this.outPath = outPath;
    }

    @Override
    public void open(ExecutionContext executionContext) throws ItemStreamException {
        try {
            Path parent = outPath.getParent();
            if (parent != null) {
                Files.createDirectories(parent);
            }
        } catch (IOException e) {
            throw new ItemStreamException(e);
        }
        this.wb = new XSSFWorkbook();
    }

    @Override
    public void write(Chunk<? extends Map<String, Object>> chunk) throws Exception {
        // 兜底：有时候 open 没被调到
        if (this.wb == null) {
            try {
                Path parent = outPath.getParent();
                if (parent != null) {
                    Files.createDirectories(parent);
                }
                this.wb = new XSSFWorkbook();
            } catch (IOException e) {
                throw new ItemStreamException(e);
            }
        }

        for (Map<String, Object> m : chunk.getItems()) {
            String diffType = Objects.toString(m.get("diff_type"), "UNKNOWN");
            Sheet s = sheets.computeIfAbsent(diffType, k -> {
                Sheet ns = wb.createSheet(k);
                createHeader(ns);
                return ns;
            });
            int rowIdx = s.getLastRowNum() == 0 ? 1 : s.getLastRowNum() + 1;
            Row r = s.createRow(rowIdx);
            int c = 0;
            r.createCell(c++).setCellValue(Objects.toString(m.get("tx_date"), ""));
            r.createCell(c++).setCellValue(Objects.toString(m.get("account_no"), ""));
            r.createCell(c++).setCellValue(Objects.toString(m.get("order_no"), ""));
            r.createCell(c++).setCellValue(toDouble(m.get("core_amount")));
            r.createCell(c++).setCellValue(toDouble(m.get("bank_amount")));
            r.createCell(c++).setCellValue(Objects.toString(m.get("core_currency"), ""));
            r.createCell(c++).setCellValue(Objects.toString(m.get("bank_currency"), ""));
            r.createCell(c).setCellValue(diffType);
        }
    }

    private void createHeader(Sheet s) {
        Row h = s.createRow(0);
        String[] heads = {
            "TX_DATE", "ACCOUNT_NO", "ORDER_NO",
            "CORE_AMOUNT", "BANK_AMOUNT",
            "CORE_CCY", "BANK_CCY",
            "DIFF_TYPE"
        };
        for (int i = 0; i < heads.length; i++) {
            h.createCell(i).setCellValue(heads[i]);
        }
    }

    private double toDouble(Object v) {
        if (v == null) {
            return 0d;
        }
        if (v instanceof Number n) {
            return n.doubleValue();
        }
        try {
            return new BigDecimal(v.toString()).doubleValue();
        } catch (Exception e) {
            return 0d;
        }
    }

    @Override
    public void close() throws ItemStreamException {
        if (this.wb == null) {
            return;
        }
        try (FileOutputStream fos = new FileOutputStream(outPath.toFile())) {
            this.wb.write(fos);
        } catch (IOException e) {
            throw new ItemStreamException(e);
        }
    }
}
